package com.examination.client.util;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.codec.binary.Base64;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Formatter;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import static com.examination.client.util.HttpUtil.httpsRequest;

@Component
public class OpenIdUtils {

    private static LogUtil logger = new LogUtil(OpenIdUtils.class);

    /**
     * 微信公众号获取openId
     */
    private static final String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";

    /**
     * 微信小程序获取openId
     */
    private static final String ACCESS_TOKEN_SMALL_URL = "https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code";

    /**
     * 运管小程序
     */
    private final static String WECHAT_APPLET = "wechat_applet";
    //小程序
    private static final String appIdSNS = "wxc304353701749c5e";
    private static final String appSecretSNS = "2b4ce579aeac6698f84bb0eda08af09f";

    /**
     * 运管微信
     */
    private final static String WECHAT_PUBLIC = "wechat_public";

    //    private final static String wx_app_id="wx48b70e55be8deae3";
    private final static String wx_app_id = "wx06965f909bdf6933";

    private final static String wx_app_id_test = "wx06965f909bdf6933";

    //    private final static String APP_SECRET = "94f20088448d9695f76b113a0e2c5757";
    private final static String APP_SECRET = "1a9f014129325b771274065ac928bbf8";

    private final static String APP_SECRET_TEST = "1a9f014129325b771274065ac928bbf8";


    /**
     * 跨城闪送小程序
     */
    private final static String WECHAT_APPLETKucCheng = "wechat_applet_kuaCheng";
    private static final String appIdKuaCheng = "wxa04954c3cbc95a42";
    private static final String appSecretKuaCheng = "28f5f9d3cd42060dcd1cf19594c64701";

    /**
     * 微信重定向网页,获取opinid.
     *
     * @param appId
     * @param code
     * @return
     */
    public static String getOpenid(String type, String appId, String code, String profiles) {
        String app_secret = APP_SECRET;
        if (!"prod".equals(profiles)) {
            app_secret = APP_SECRET_TEST;
        }

        String openId = null;
        JSONObject jsonObject = new JSONObject();
        if (WECHAT_PUBLIC.equals(type)) {

            String replaceUrl = ACCESS_TOKEN_URL.replace("APPID", appId).replace("SECRET", app_secret).replace("CODE", code);
            logger.info(replaceUrl);
            jsonObject = JSON.parseObject(httpsRequest(replaceUrl, HttpMethod.GET.name(), null));
            openId = jsonObject.getString("openid");
        } else if (WECHAT_APPLET.equals(type)) {
            String replaceUrl = ACCESS_TOKEN_SMALL_URL.replace("APPID", appId).replace("SECRET", appSecretSNS).replace("JSCODE", code);
            jsonObject = JSON.parseObject(httpsRequest(replaceUrl, HttpMethod.POST.name(), null));
            openId = jsonObject.getString("openid");
        }
        if (null != openId) {
            logger.info("getOpenId:{}", openId);
        } else {
            openId = jsonObject.getString("errcode");
        }
        return openId;
    }

    //跨城闪送小程序获取openId、sessionKey
    public static Map<String,String> getOpenIdAndSessionKey(String code) {
        JSONObject jsonObject = new JSONObject();
        String replaceUrl = ACCESS_TOKEN_SMALL_URL.replace("APPID", appIdKuaCheng).replace("SECRET", appSecretKuaCheng).replace("JSCODE", code);
        jsonObject = JSON.parseObject(httpsRequest(replaceUrl, HttpMethod.POST.name(), null));
        logger.info(replaceUrl);
        Map<String,String> stringHashMap = new HashMap<String,String>();
        stringHashMap.put("openid",jsonObject.getString("openid"));
        stringHashMap.put("session_key",jsonObject.getString("session_key"));
        return stringHashMap;
    }

    public static final String ACCESS_TOKEN_URL_SIGN = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + wx_app_id + "&secret=" + APP_SECRET + "";
    public static final String ACCESS_TOKEN_URL_SIGN_TEST = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + wx_app_id_test + "&secret=" + APP_SECRET_TEST + "";

    public static Map<String, String> sign(String url, String profiles) {
        //获取JS-SDK的 accesstoken 注意:其与获取网页授权的accesstoken不同

        String str = ACCESS_TOKEN_URL_SIGN;
        if (!"prod".equals(profiles)) {
            str = ACCESS_TOKEN_URL_SIGN_TEST;
        }

        JSONObject jsonObject = JSON.parseObject(httpsRequest(str, HttpMethod.GET.name(), null));
        String accesToken = (String) jsonObject.get("access_token");
        System.out.println("微信返回accesToken" + accesToken);

        //获取ticket
        JSONObject jsapiTicketObject = JSON.parseObject(httpsRequest("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + accesToken + "&type=jsapi", HttpMethod.GET.name(), null));
        String jsapiTicket = (String) jsapiTicketObject.get("ticket");
        System.out.println("微信返回jsapiTicket" + jsapiTicket);

        Map<String, String> ret = new HashMap<String, String>();
        String nonce_str = create_nonce_str();
        String timestamp = create_timestamp();
        String string1;
        String signature = "";

        //注意这里参数名必须全部小写，且必须有序
        string1 = "jsapi_ticket=" + jsapiTicket +
                "&noncestr=" + nonce_str +
                "&timestamp=" + timestamp +
                "&url=" + url;
        System.out.println("string1=" + string1);

        try {
            MessageDigest crypt = MessageDigest.getInstance("SHA-1");
            crypt.reset();
            crypt.update(string1.getBytes("UTF-8"));
            //换取签名
            signature = byteToHex(crypt.digest());
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }

        ret.put("url", url);
        ret.put("jsapi_ticket", jsapiTicket);
        ret.put("nonceStr", nonce_str);
        ret.put("timestamp", timestamp);
        ret.put("signature", signature);
        ret.put("appId", wx_app_id);  //此时可通过配置引入
        if (!"prod".equals(profiles)) {
            ret.put("appId", wx_app_id_test);  //此时可通过配置引入
        }
        System.out.println("1.ticket(原始)=" + jsapiTicket);
        System.out.println("2.url=" + ret.get("url"));
        System.out.println("3.jsapi_ticket（处理后）=" + ret.get("jsapi_ticket"));
        System.out.println("4.nonceStr=" + ret.get("nonceStr"));
        System.out.println("5.signature=" + ret.get("signature"));
        System.out.println("6.timestamp=" + ret.get("timestamp"));

        return ret;
    }

    /**
     * 随机加密
     *
     * @param hash
     * @return
     */
    private static String byteToHex(final byte[] hash) {
        Formatter formatter = new Formatter();
        for (byte b : hash) {
            formatter.format("%02x", b);
        }
        String result = formatter.toString();
        formatter.close();
        return result;
    }

    /**
     * 产生随机串--由程序自己随机产生
     *
     * @return
     */
    private static String create_nonce_str() {
        return UUID.randomUUID().toString();
    }

    /**
     * 由程序自己获取当前时间
     *
     * @return
     */
    private static String create_timestamp() {
        return Long.toString(System.currentTimeMillis() / 1000);
    }

    /**
     * 解开用户手机号的密文
     *
     * @param encData
     * @param iv
     * @param session_key
     */
    public static String deco(String encData, String iv, String session_key) {
        try {
            String resultMessage =
                    AES.decrypt(
                            Base64.decodeBase64(session_key),
                            Base64.decodeBase64(iv)
                            , Base64.decodeBase64(encData));

            return resultMessage;
        } catch (Exception e) {
            //e.printStackTrace();
            return null;
        }
    }

}
